package com.ndood.authenticate.browser.session;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ndood.core.properties.CommonConstants;
import com.ndood.core.properties.SecurityProperties;
import com.ndood.core.support.SimpleResponse;

/**
 * 抽象的session失效处理器
 */
public class AbstractSessionStrategy {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	/**
	 * 跳转的url
	 */
	private String destinationUrl;
	/**
	 * 系统配置信息
	 */
	private SecurityProperties securityPropertie;
	/**
	 * 重定向策略
	 */
	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
	/**
	 * 跳转前是否创建新的session
	 */
	private boolean createNewSession = true;

	private ObjectMapper objectMapper = new ObjectMapper();

	public AbstractSessionStrategy(SecurityProperties securityPropertie) {
		String invalidSessionUrl = securityPropertie.getBrowser().getSession().getSessionInvalidUrl();
		Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl), "url must start with '/' or with 'http(s)'");
		// Assert.isTrue(StringUtils.endsWithIgnoreCase(invalidSessionUrl, ".html"), "url must end with '.html'");
		this.destinationUrl = invalidSessionUrl;
		this.securityPropertie = securityPropertie;
	}

	/**
	 * TODO 改造跳转方式，json|ajax跳转 vs 普通跳转
	 */
	protected void onSessionInvalid(HttpServletRequest request, HttpServletResponse response) throws IOException {
		logger.info("session失效");
		if (createNewSession) {
			request.getSession();
		}
		String sourceUrl = request.getRequestURI();
		String targetUrl;
		/*if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")
				||StringUtils.endsWithIgnoreCase(sourceUrl, "/")
				||StringUtils.endsWithIgnoreCase(sourceUrl, "index")) {
			if(StringUtils.equals(sourceUrl, securityPropertie.getBrowser().getSignInPage())){
				targetUrl = sourceUrl;
			}else{
				targetUrl = destinationUrl;
			}
			logger.info("跳转到:"+targetUrl);
			redirectStrategy.sendRedirect(request, response, targetUrl);
		} else {
			Object result = buildResponseContent(request);
			response.setStatus(HttpStatus.UNAUTHORIZED.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(result));
			response.getWriter().flush();
		}*/

		if(isAjax(request)|isJson(request)) {
			Object result = buildResponseContent(request);
			response.setStatus(HttpStatus.UNAUTHORIZED.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(objectMapper.writeValueAsString(result)));
			response.getWriter().flush();
			return;
		}
		if(StringUtils.equals(sourceUrl, securityPropertie.getBrowser().getSignInPage())){
			targetUrl = sourceUrl;
		}else{
			targetUrl = destinationUrl;
		}
		logger.info("跳转到:"+targetUrl);
		redirectStrategy.sendRedirect(request, response, targetUrl);
		
	}
	
	/**
	 * 判断是否是json请求
	 */
	public Boolean isJson(HttpServletRequest request) {
		boolean isJson = request.getHeader("content-type") != null
				&& request.getHeader("content-type").contains("json");
		return isJson;
	}

	/**
	 * 判断是否是ajax请求
	 */
	public static boolean isAjax(HttpServletRequest httpRequest) {
		boolean isAjax = httpRequest.getHeader("X-Requested-With") != null
				&& "XMLHttpRequest".equals(httpRequest.getHeader("X-Requested-With").toString());
		return isAjax;
	}

	protected Object buildResponseContent(HttpServletRequest request) {
		String message = "session已失效";
		if (isConcurrency()) {
			message = message + "，有可能是并发登录导致的";
		}
		return new SimpleResponse(CommonConstants.FAILUE, message);
	}

	/**
	 * session失效是否是并发导致的
	 */
	protected boolean isConcurrency() {
		return false;
	}

	public void setCreateNewSession(boolean createNewSession) {
		this.createNewSession = createNewSession;
	}

}